﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Xml.Linq;
using doveData;

namespace WindowsFormsApp1
{
    public partial class TestView : UserControl
    {
        private int m_Size = 10;
        private int m_Power = 15;
        private int m_Move = 5;
        private int m_minDist = 5;

        private float m_zoomScale = 1;
        private float m_scrollX;
        private float m_scrollY;

        public List<Station> SelectedLineList=new List<Station>();
        public List<Point> HighLightPoints=new List<Point>();
        public bool isPath =true;

        private Point m_mouseDownPoint = Point.Empty;
        private Point m_mouseLastPoint = Point.Empty;

        [DefaultValue(1)]
        public float ZoomScale
        {
            get { return m_zoomScale; }
            set
            {
                if (m_zoomScale!=value)
                {
                    m_zoomScale = Math.Max(value,0.1f);
                    Invalidate();
                }
            }
        }
        [DefaultValue(0)]
        public float ScrollX
        {
            get { return m_scrollX; }
            set
            {
                if (m_scrollX!=value)
                {
                    m_scrollX = value;
                    Invalidate();
                }
                
            }
        }
        [DefaultValue(0)]
        public float ScrollY
        {
            get { return m_scrollY; }
            set
            {
                if (m_scrollY != value)
                {
                    m_scrollY = value;
                    Invalidate();
                }
            }
        }




        public TestView()
        {
            InitializeComponent();

            //优化绘图
            SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer
                | ControlStyles.ResizeRedraw | ControlStyles.UserPaint, true);
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);
            
            e.Graphics.TranslateTransform(this.ScrollX, this.ScrollY);
            e.Graphics.ScaleTransform(this.ZoomScale, this.ZoomScale);

            //根据组别显示对象
            PaintGroup(e);
        }

        private void PaintGroup(PaintEventArgs e)
        {
            
            if (checkBox1.Checked)
            {
                PaintLine(e.Graphics, StatContrl.AllStation);
                PaintStation(e.Graphics, StatContrl.AllStation);
                if (SelectedLineList.Count!=0)
                {
                    if (isPath)
                    {
                        HighLightLine(e.Graphics,StatContrl.AllStation,SelectedLineList);
                    }
                    HighLightStation(e.Graphics, SelectedLineList);
                }
                
            }
            if (checkBox2.Checked)
            {
                PaintHotel(e.Graphics);
            }
            if (checkBox3.Checked)
            {
                PaintFood(e.Graphics);
            }
            if (checkBox4.Checked)
            {
                PaintMarket(e.Graphics);
            }

        }

        private Rectangle ToFormRect(int posX, int posY, int width, int height)
        {
            return new Rectangle(m_Power*posX-width/2,m_Power*posY-height/2,width,height);
        }

        private Point ToFormPoint(int x,int y)
        {
            return  new Point(m_Power * x, m_Power * y);
        }


        private void PaintStation(Graphics g, StationGraph<Station> all)
        {
            for (int i = 0; i < all.Count; i++)
            {
                Station tempStation = all.GetItem(i);
                Point pm = ToFormPoint((int) tempStation.Location.X, (int) tempStation.Location.Y);
                PaintOneStation(g,tempStation,pm);
            }
        }

        private void HighLightStation(Graphics g,List<Station> stations )
        {
            for (int i = 0; i < stations.Count; i++)
            {
                Station tempStation = stations[i];
                Point pm = ToFormPoint((int)tempStation.Location.X, (int)tempStation.Location.Y);
                HighLightOneStation(g, tempStation, pm);
            }
        }

        private void HighLightLine(Graphics g, StationGraph<Station> all,List<Station> stations)
        {
            for (int i = 0; i < stations.Count; i++)
            {
                Point p1 = ToFormPoint((int)stations[i].Location.X, (int)stations[i].Location.Y);
                if (stations.Count>=2&&i>0)
                {
                    Point p2 = ToFormPoint((int)stations[i-1].Location.X, (int)stations[i-1].Location.Y);
                    Pen pen=new Pen(Color.GreenYellow,5);
                    g.DrawLine(pen, p1, p2);
                }
            }
        }

        public void ResetPath()
        {
            SelectedLineList.Clear();
            isPath = false;
        }

        private void PaintOneStation(Graphics g, Station station,Point pm)
        {
            var rect = ToFormRect((int)station.Location.X, (int)station.Location.Y, m_Size, m_Size);
            g.FillEllipse(Brushes.White, rect);
            g.DrawEllipse(Pens.Black, rect);
            string name = station.Name;
            Size nameSize = TextRenderer.MeasureText(name, this.Font);
            g.DrawString(name, this.Font, Brushes.Black, pm.X - nameSize.Width / 2, pm.Y + nameSize.Height / 2);
        }
        private void HighLightOneStation(Graphics g, Station station, Point pm)
        {
            var rect = ToFormRect((int)station.Location.X, (int)station.Location.Y, m_Size, m_Size);
            g.FillEllipse(Brushes.Green, rect);
            g.DrawEllipse(Pens.White, rect);
        }

        private void PaintLine(Graphics g, StationGraph<Station> all)
        {
            for (int i = 0; i < all.Count; i++)
            {
                for (int j = 0; j < all.Count; j++)
                {
                    if (all.Edges[i,j]!=65535)
                    {
                        Point p1, p2;
                        Station s1, s2;
                        s1 = all.GetItem(i);
                        s2 = all.GetItem(j);
                        p1 = ToFormPoint((int) s1.Location.X, (int) s1.Location.Y);
                        p2 = ToFormPoint((int)s2.Location.X, (int)s2.Location.Y);
                        String line="";
                        foreach (string lineDictKey in s1.LineDict.Keys)
                        {
                            if (s2.LineDict.ContainsKey(lineDictKey))
                            {
                                line = lineDictKey;
                            }
                        }
                        Pen pen=new Pen(Color.Black,5);
                        switch (line)
                        {
                            case "1":pen.Color = Color.Yellow;
                                break;
                            case "2":pen.Color = Color.Blue;
                                break;
                            case "5":
                                pen.Color = Color.Red;
                                break;
                            case "6":
                                pen.Color = Color.DeepPink;
                                break;
                        }

                        g.DrawLine(pen,p1,p2);
                    }
                }
            }
        }

        private void PaintFood(Graphics g)
        {
            Color color = Color.Orange;
            for (int i = 0; i < StatContrl.AllFood.Count; i++)
            {
                Food food = StatContrl.AllFood[i];
                PaintOneFood(g,food,color);
            }
        }
        private void PaintHotel(Graphics g)
        {
            Color color = Color.HotPink;
            for (int i = 0; i < StatContrl.AllHotel.Count; i++)
            {
                Hotel hotel = StatContrl.AllHotel[i];
                PaintOneHotel(g, hotel, color);
            }
        }
        private void PaintMarket(Graphics g)
        {
            Color color = Color.CornflowerBlue;
            for (int i = 0; i < StatContrl.AllMarket.Count; i++)
            {
                Market market = StatContrl.AllMarket[i];
                PaintOneMarket(g, market, color);
            }
        }
       public void PaintOneFood(Graphics g,Food food,Color color)
        {
            Brush brush=new SolidBrush(color);
            var rect = ToFormRect((int)food.Location.X, (int)food.Location.Y, m_Size, m_Size);
            g.FillEllipse(brush, rect);
            g.DrawEllipse(Pens.Black, rect);
        }
        public void PaintOneHotel(Graphics g, Hotel hotel, Color color)
        {
            Brush brush = new SolidBrush(color);
            var rect = ToFormRect((int)hotel.Location.X, (int)hotel.Location.Y, m_Size, m_Size);
            g.FillEllipse(brush, rect);
            g.DrawEllipse(Pens.Black, rect);
        }
        public void PaintOneMarket(Graphics g, Market market, Color color)
        {
            Brush brush = new SolidBrush(color);
            var rect = ToFormRect((int)market.Location.X, (int)market.Location.Y, m_Size, m_Size);
            g.FillEllipse(brush, rect);
            g.DrawEllipse(Pens.Black, rect);
        }
        #region 重写鼠标操作

        /// <summary>
        /// 重写OnMouseDown方法。
        /// </summary>
        /// <param name="e"></param>
        protected override void OnMouseDown(MouseEventArgs e)
        {
            m_mouseDownPoint = e.Location;
            m_mouseLastPoint = e.Location;
        }

        /// <summary>
        /// 重写OnMouseUp方法。
        /// </summary>
        /// <param name="e"></param>
        protected override void OnMouseUp(MouseEventArgs e)
        {
            Invalidate();
        }

        /// <summary>
        /// 重写OnMouseMove方法。
        /// </summary>
        /// <param name="e"></param>
        protected override void OnMouseMove(MouseEventArgs e)
        {
            
            //label2.Text = ScrollX + "," + ScrollY + "\n" + e.X + "," + e.Y+"\n"+ZoomScale;
            panel1.Visible = false;
            if (e.Button == MouseButtons.Left)
            {
                this.ScrollX += e.X - m_mouseLastPoint.X;
                this.ScrollY += e.Y - m_mouseLastPoint.Y;
                m_mouseLastPoint = e.Location;

            }
            if (checkBox1.Checked)
            {
            }
            if (checkBox2.Checked)
            {
                for (int i = 0; i < StatContrl.AllHotel.Count; i++)
                {
                    Point temp = ToFormPoint((int)StatContrl.AllHotel[i].Location.X, (int)StatContrl.AllHotel[i].Location.Y);
                    temp.X =(int)(temp.X*ZoomScale);
                    temp.Y = (int)(temp.Y * ZoomScale);
                    temp.X +=(int) ScrollX;
                    temp.Y += (int)ScrollY;
                    double tmf = FormDistance(temp, e.Location);
                    if (tmf < m_minDist)
                    {
                        panel1.Location = e.Location;
                        label1.Text = StatContrl.AllHotel[i].Name;
                        panel1.Visible = true;
                        Invalidate();
                    }
                }
            }
            if (checkBox3.Checked)
            {
                for (int i = 0; i < StatContrl.AllFood.Count; i++)
                {
                    Point temp = ToFormPoint((int)StatContrl.AllFood[i].Location.X, (int)StatContrl.AllFood[i].Location.Y);
                    temp.X = (int)(temp.X * ZoomScale);
                    temp.Y = (int)(temp.Y * ZoomScale);
                    temp.X += (int)ScrollX;
                    temp.Y += (int)ScrollY;
                    double tmf = FormDistance(temp, e.Location);

                    if (tmf < m_minDist)
                    {
                        panel1.Location = e.Location;
                        label1.Text = StatContrl.AllFood[i].Name;
                        panel1.Visible = true;
                        Invalidate();
                    }
                }
            }
            if (checkBox4.Checked)
            {
                for (int i = 0; i < StatContrl.AllMarket.Count; i++)
                {
                    Point temp = ToFormPoint((int)StatContrl.AllMarket[i].Location.X, (int)StatContrl.AllMarket[i].Location.Y);
                    temp.X = (int)(temp.X * ZoomScale);
                    temp.Y = (int)(temp.Y * ZoomScale);
                    temp.X += (int)ScrollX;
                    temp.Y += (int)ScrollY;
                    double tmf = FormDistance(temp, e.Location); 
                    if (tmf < m_minDist)
                    {
                        panel1.Location = e.Location;
                        label1.Text = StatContrl.AllMarket[i].Name;
                        panel1.Visible = true;
                        Invalidate();
                    }
                }
            }
        }

        /// <summary>
        /// 重写OnMouseWheel方法。
        /// </summary>
        /// <param name="e"></param>
        protected override void OnMouseWheel(MouseEventArgs e)
        {
            this.ZoomScale += (e.Delta > 0 ? 0.1f : -0.1f);
        }

        private double FormDistance(Point p1, Point p2)
        {
            return Math.Sqrt(Math.Pow(p1.X - p2.X, 2) + Math.Pow(p1.Y - p2.Y, 2));
        }

        #endregion

        #region 改变显示组别
        private void checkBox1_CheckedChanged(object sender, EventArgs e)
        {
            Invalidate();
        }

        private void checkBox2_CheckedChanged(object sender, EventArgs e)
        {
            Invalidate();
        }

        private void checkBox3_CheckedChanged(object sender, EventArgs e)
        {
            Invalidate();
        }

        private void checkBox4_CheckedChanged(object sender, EventArgs e)
        {
            Invalidate();
        }
        #endregion

        private void TestView_Load(object sender, EventArgs e)
        {
            checkBox1.Checked = true;
        }
    }

    
    
}
